import json
import logging
from django.views.decorators.http import require_POST, require_GET
from django.views.generic import TemplateView
from common.user import db, handler
from common.account import db as account_db
from common.merchant import handler as merchant_handler
from common.utils.api import token_required
from django.utils.decorators import method_decorator
from common.utils.decorator import response_wrapper, validate_form, check_user_vcode
from common.utils.maestro_exceptions import (
    MaestroException,
    ILLEGAL_PARAMETER,
    ACCESS_DENIED
)
from .users_form import (
    UserLoginForm,
    UserCreateForm,
    UpdateUserMerchantRoleForm,
    UserListForm,
    UserUpdateForm,
    ResetUserPasswordForm
)

_LOGGER = logging.getLogger(__name__)


@require_POST
@response_wrapper
@validate_form(UserLoginForm)
def login(req, cleaned_data):
    username, password = cleaned_data['username'], cleaned_data['password']
    user = db.login_user(username, password)
    check_user_vcode(req, user['id'])
    return user


@require_POST
@response_wrapper
@token_required
def logout(req):
    db.logout_user(req.user_id)
    return {}


class UserView(TemplateView):
    @method_decorator(token_required)
    @method_decorator(validate_form(UserListForm))
    def get(self, req, cleaned_data, *args, **kwargs):
        user_id = req.user_id
        merchant_id = req.merchant_id
        role_id_list = cleaned_data['role']
        page, size = cleaned_data['page'], cleaned_data['size']
        paginator_dct = dict(page=page, size=size)
        user_filter_dct = {k: value for k, value in cleaned_data.items() if k in ('id', 'username',) and value}
        return merchant_handler.list_merchant_user(merchant_id, user_id, role_id_list, user_filter_dct,
                                                   paginate_dct=paginator_dct)

    @method_decorator(validate_form(UserCreateForm))
    def post(self, req, cleaned_data):
        query_dct = json.loads(req.body)
        username, password = cleaned_data['username'], cleaned_data['password']
        db.create_user(username, password)
        _LOGGER.info('register user: %s', query_dct)
        return dict()

    @method_decorator(response_wrapper)
    def dispatch(self, *args, **kwargs):
        return super(UserView, self).dispatch(*args, **kwargs)


class SingleUserView(TemplateView):
    def get(self, req, user_id):
        user_id = int(user_id)
        user = db.get_user(user_id)
        info = user.__dict__ if user else {}
        info['created_at'], info['updated_at'] = str(info['created_at']), str(info['updated_at'])
        info.pop('_state', None)
        info.pop('password', None)
        return info

    @method_decorator(validate_form(UserUpdateForm))
    def put(self, req, user_id, cleaned_data):
        valid_params = dict(id=int(user_id))
        password = cleaned_data['password']
        current_password = cleaned_data['current_password']
        if password:
            if not current_password:
                raise MaestroException(ILLEGAL_PARAMETER, '修改密码参数错误')
            user = req.user
            if db.encode_password(current_password) != user.password:
                raise MaestroException(ACCESS_DENIED)
            valid_params['password'] = password
        db.update_user(valid_params)
        if password:
            db.logout_user(req.user_id)
        _LOGGER.info('update user: %s, by %s', valid_params, req.user.id)
        return dict()

    def delete(self, req, user_id):
        is_root = req.is_root
        check_user_vcode(req)
        if not is_root:
            raise MaestroException(ACCESS_DENIED)
        db.delete_user(int(user_id))
        return dict()

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleUserView, self).dispatch(*args, **kwargs)


@require_POST
@response_wrapper
@token_required
@validate_form(UpdateUserMerchantRoleForm)
def update_user_merchant_role(req, cleaned_data):
    merchant_id = req.merchant_id
    admin_id = req.user_id
    user_id = cleaned_data['user_id']
    new_role_id = cleaned_data['new_role_id']
    description = cleaned_data['description']
    check_user_vcode(req, admin_id)
    handler.update_user_merchant_role(merchant_id, admin_id, user_id, new_role_id, description)
    return dict()


@require_GET
@response_wrapper
@token_required
def get_user_chn(req):
    merchant_name = req.merchant_name
    return dict(chn_list=account_db.get_distinct_channel(merchant_name))


@require_GET
@response_wrapper
@token_required
def get_user_preset(req):
    user_id = req.user_id
    user_preset = dict(list=[])
    user_role_level = merchant_handler.get_user_roles_information(user_id)
    user_preset['is_root'] = user_role_level['is_root']
    for key, value in user_role_level.items():
        if key not in ('is_root', 'root',):
            value.update({'merchant_id': key})
            user_preset['list'].append(value)
    return user_preset


@require_GET
@response_wrapper
def get_update_user_role_preset(req):
    merchant_id = req.merchant_id
    admin_role_id = req.merchant_role.get('id')
    merchant_role = req.merchant_role
    role_level = merchant_role['role_level']
    return dict(available=handler.get_available_role_id_list(merchant_id, admin_role_id, role_level))


@require_POST
@response_wrapper
@token_required
@validate_form(ResetUserPasswordForm)
def reset_password(req, cleaned_data):
    merchant_id = req.merchant_id
    admin_id = req.user_id
    user_id = cleaned_data['user_id']
    check_user_vcode(req, admin_id)
    handler.reset_user_password(merchant_id, admin_id, user_id)
    return dict()
